#!/usr/bin/perl 
use strict;
use warnings;
use Cwd qw(abs_path);
use File::Spec;
use File::Spec::Functions;

our %params = (
    dmoz_dir   => '/home/xuqy/Desktop/dmoz',
);

chdir $params{dmoz_dir} or die "$!";

our @ancestors;
our $count = 0;

&process('Top', 'Top');

print STDERR "Done! $count path cycles detected!\n";

sub process {
    my ($path, $suffix) = @_;
    push @ancestors, [$suffix, $path];
    opendir my $dir, $path or die "$!";
    while (my $entry = readdir $dir) {
        next if $entry =~ /^\.{1,2}$/;
        my $subDir = catfile($path, $entry);
        next unless -d $subDir;
        my $canonical = &get_canonical($path, $subDir);
        my $flag = 1;
        for my $i (0..$#ancestors) {
            if ($canonical eq $ancestors[$i][1]) {
                $flag = 0;
                print "From: ", join('/', map { $_->[0] } @ancestors), "\n";
                print "To  : $entry\n";
                print "From: ", join(' -> ', map {$_->[1]} @ancestors), "\n";
                print "To  : $canonical\n\n";
                $count++;
                last;
            }
        }
        if ($flag) {
            &process($canonical, $entry);
        }
    }
    closedir $dir;
    pop @ancestors;
}

sub get_canonical {
    my ($parent, $entry) = @_;
    if (-l $entry) {
        my $abs = File::Spec->rel2abs(readlink($entry), $parent);
        my $canon = abs_path($abs);
        return File::Spec->abs2rel($canon);
    }
    else {
        return $entry;
    }
}
